#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Predesys - Predesys Bluetooth Radar
# Version: 0.1.2
# Author: Jose A. Jimenez <jajimc@gmail.com>
# License: GPL 3.0 (see "license" file)

import sys
sys.dont_write_bytecode = True
import os
import simplexml
import radarexceptions

# Configuration file path to load
CONFIG_FILE_1 = "configuration.xml"
CONFIG_FILE_2 = "/etc/predesys-bluetooth-radar/configuration.xml"
    
# Default server web service settings
DEFAULT_SERVER_WEBSERVICE_ADDRESS = "http://localhost:8000"

# Default server authentication settigs
DEFAULT_USER_NAME = "station"
DEFAULT_USER_PASSWORD = "station"

# Default bluetooth settings
DEFAULT_SCAN_INTERVAL = 20
DEFAULT_CONNECTION_TIMEOUT = 10

class RadarConfiguration():
    """Class that represents the Predesys Radar settings."""
    def __init__(self):
        """Class constructor.
        
        It initialize the object with the default values.
        """
        self.set_default_values()
        
    def set_default_values(self):
        self.set_server_webservice_address(DEFAULT_SERVER_WEBSERVICE_ADDRESS)
        self.set_user_id(DEFAULT_USER_NAME)
        self.set_user_password(DEFAULT_USER_PASSWORD)
        self.set_scan_interval(DEFAULT_SCAN_INTERVAL)
        self.set_connection_timeout(DEFAULT_CONNECTION_TIMEOUT)
        
    def get_server_webservice_address(self):
        return self.__serverWebServiceAddress
        
    def get_user_id(self):
        return self.__userId
        
    def get_user_password(self):
        return self.__userPassword
        
    def get_scan_interval(self):
        return self.__scanInterval
        
    def get_connection_timeout(self):
        return self.__connectionTimeout

    def set_server_webservice_address(self, address):
        if address == None or type(address) != str:
            raise radarexceptions.ValueNotValidException("'address' must be a not null string.")
        
        self.__serverWebServiceAddress = address
        
    def set_user_id(self, userId):
        if userId == None or type(userId) != str or userId == "":
            raise radarexceptions.ValueNotValidException("User ID must be a not null and not empty string.")
            
        self.__userId = userId
        
    def set_user_password(self, userPassword):
        if userPassword == None or type(userPassword) != str or userPassword == "":
            raise radarexceptions.ValueNotValidException("User password must be a not null and not empty string.")
            
        self.__userPassword = userPassword
        
    def set_scan_interval(self, time):
        if time == None or type(time) != int or time < 0:
            raise radarexceptions.ValueNotValidException("'time' must be an integer greater than 0.")
            
        self.__scanInterval = time
        
    def set_connection_timeout(self, time):
        if time == None or type(time) != int or time < 0:
            raise radarexceptions.ValueNotValidException("'time' must be an integer greater than 0.")
            
        self.__connectionTimeout = time

    def load_from_file(self, path):
        """Loads settings from a XML file.
        
        Keyword arguments:
        path -- File path from wich load settings (string)
        
        It raises an exception (ValueNotValidException) if path isn't a valid file path.
        It raises an exception (FileNotFoundException) if file doesn't exist.
        It raises an exception (LoadFileException) if an error occurs loading the file.
        """
        if path == None or type(path) != str or path == "": raise radarexceptions.ValueNotValidException("Path must be a valid file path.")
        if not (os.path.exists(path) and os.path.isfile(path)): raise radarexceptions.FileNotFoundException("Configuration file doesn't exist.")
        
        try:
            document = simplexml.SimpleXmlDocument(path)          
            self.set_server_webservice_address(document.get_text_node_value("server_webservice_address", 0))
            self.set_user_id(document.get_text_node_value("user_id", 0))
            self.set_user_password(document.get_text_node_value("user_password", 0))
            self.set_scan_interval(int(document.get_text_node_value("scan_interval", 0)))
            self.set_connection_timeout(int(document.get_text_node_value("connection_timeout", 0)))
        except:
            raise LoadFileException("Configuration load error.")
            
    def save_to_file(self, path):
        """Saves settings to a file.
        
        Keyword arguments:
        path -- File path to save settings (string)
        
        It raises an exception (ValueNotValidException) if path isn't a valid file path.
        It raises an exception (SaveFileException) if an error occurs saving the file.
        """
        security.check_root()
        if path == None or type(path) != str or path == "": raise radarexceptions.ValueNotValidException("Path must be a valid file path.")
        
        content = "<?xml version=\"1.0\" ?>\n"
        content += "<configuration>"
        content += "\t<server_webservice_address>%s</server_webservice_address>\n" % self.get_server_webservice_address()
        content += "\t<user_id>%s</user_id>\n" % self.get_user_id()
        content += "\t<user_password>%s</user_password>\n" % self.get_user_password()
        content += "\t<scan_interval>%d</scan_interval>\n" % self.get_scan_interval()
        content += "\t<connection_timeout>%d</connection_timeout>\n" % self.get_connection_timeout()
        content += "</configuration>"
        
        try:
            with open(path, "w") as configFile:
                configFile.write(content)
        except:
            raise radarexceptions.SaveFileException("Configuration save error.")
    
def load_configuration():
    """Loads configuration from CONFIG_FILE_1 file or CONFIG_FILE_2 file.
        
    If an error occurs, it sets the default configuration.
    """
    config = RadarConfiguration()
        
    if os.path.isfile(CONFIG_FILE_1):
        try:
            config.load_from_file(CONFIG_FILE_1)
        except:
            if os.path.isfile(CONFIG_FILE_2):
                try:
                    config.load_from_file(CONFIG_FILE_2)
                except:
                    config.set_default_values()
            else:
                config.set_default_values()
    elif os.path.isfile(CONFIG_FILE_2):
        try:
            config.load_from_file(CONFIG_FILE_2)
        except:
            config.set_default_values()
    else:
        config.set_default_values()

    return config
